home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / cmdity / yk212src.lha / Yak_2.12_Src / WBStartup / Hotkey_actions.c < prev    next >
C/C++ Source or Header  |  1996-01-25  |  33KB  |  1,463 lines

  1.  
  2. #define __USE_SYSBASE
  3.  
  4.  
  5. #include <proto/exec.h>
  6. #include <proto/dos.h>
  7. #include <proto/graphics.h>
  8. #include <proto/intuition.h>
  9. #include <proto/commodities.h>
  10. #include <proto/layers.h>
  11. #include <proto/locale.h>
  12. #include <proto/reqtools.h>
  13.  
  14. #include <clib/alib_protos.h>
  15.  
  16. #include <exec/types.h>
  17. #include <exec/tasks.h>
  18. #include <dos/dostags.h>
  19. #include <dos/datetime.h>
  20. #include <intuition/intuitionbase.h>
  21. #include <libraries/locale.h>
  22. #include <libraries/reqtools.h>
  23.  
  24. #include <string.h>
  25.  
  26. #include "code.h"
  27. #include "yak.h"
  28. #include "hotkey_types.h"
  29. #include "Handlers.h"
  30. #include "icon.h"
  31. #include "Settings.h"
  32. #include "Requesters.h"
  33. #include "GetScreenBox.h"
  34. #include "GetPubScreen.h"
  35. #include "Arexx.h"
  36. #include "LastActiveWindow.h"
  37.  
  38. #ifndef USE_WB2CLI
  39. #  include "wbpath.h"
  40. #endif
  41.  
  42. #define CATCOMP_NUMBERS
  43. #include "yak_locale_strings.h"
  44.  
  45. IMPORT BOOL ShowYakInterface (VOID);
  46.  
  47. static void __regargs YakMoveScreen(struct Screen *scr, UWORD flags);
  48. static void __regargs EnlargeWindow(struct Window *win, UWORD flags);
  49. static void ChangeScreen(YakOption *opt);
  50. static struct Window *SelectWindow(YakOption *opt);
  51. static struct Screen *SelectScreen(YakOption *opt);
  52. static SAVEDS ASM void putcharfunc( REG(a0) struct Hook *h,
  53.                                    REG(a2) void *object,
  54.                                    REG(a1) char c);
  55. static struct InputEvent *FlipIEvents(struct InputEvent *);
  56. static int AddToStream(char *str, UBYTE delay); 
  57. static struct Window * FindWBWindow(void);
  58. static SAVEDS void  DoPalette(void);
  59. static int palette_count;
  60. static LONG beginCommand(char *command, LONG stack, LONG Priority);
  61. static struct Window *ActiveWindow(void);
  62. static struct Screen *ActiveScreen(void);
  63.  
  64.  
  65. extern struct WBStartup *WBMsg;
  66.  
  67.  
  68. /* okay to quit? (not so if palettes open) */
  69. int
  70.    OkayToExit()
  71. {
  72.    return (palette_count == 0);
  73. }
  74.  
  75.  
  76. /* hook-function for inserting chars into input-stream */
  77. static SAVEDS ASM void 
  78.    putcharfunc(REG(a0) struct Hook *h,
  79.                REG(a2) void *object,
  80.                REG(a1) char c)
  81. {
  82.    struct InputEvent ev;
  83.    
  84.    if (c)                      /* stop at null-terminator */
  85.    {
  86.       ev.ie_NextEvent = NULL;
  87.       InvertKeyMap(c, &ev, NULL);
  88.       AddIEvents(&ev);
  89.    }
  90. }
  91. /* and its associated structure */
  92. static struct Hook putcharhook = {
  93. {NULL, NULL},
  94.    (APTR)putcharfunc,
  95.    NULL,
  96.    NULL
  97. };
  98.  
  99. /* given a list of input events, reverse their order */
  100. /* NB: the list BETTER terminate... */
  101. static struct InputEvent *
  102.    FlipIEvents(struct InputEvent *ie)
  103. {
  104.    struct InputEvent *oldtail, *newtail = NULL;
  105.    
  106.    while (ie)
  107.    {
  108.       /* remove head, set next event */
  109.       oldtail = ie->ie_NextEvent; /* this will be prev event */
  110.       ie->ie_NextEvent = newtail; /* add to head */
  111.       newtail = ie;
  112.       ie = oldtail;           /* what's left */
  113.    }
  114.    return newtail;
  115. }
  116.  
  117. /* adds a string to the input-stream */
  118.  
  119. static int
  120.    AddToStream(char *str, UBYTE delay)
  121. {
  122.    struct InputEvent *ie;
  123.    
  124.    if (ie = InvertString(str, NULL))
  125.    {
  126.       ie = FlipIEvents(ie);
  127.       
  128.       if (delay>0)
  129.       {
  130.          struct InputEvent *next;
  131.          while (ie)
  132.          {
  133.             next = ie->ie_NextEvent; 
  134.             ie->ie_NextEvent = NULL;
  135.             AddIEvents(ie);
  136.             FreeIEvents(ie);
  137.             
  138.             Delay(delay);
  139.             
  140.             ie = next;
  141.          }
  142.          
  143.       }
  144.       else
  145.       {
  146.          AddIEvents(ie);
  147.          FreeIEvents(ie);
  148.       }
  149.       return TRUE;
  150.    }
  151.    return FALSE;
  152. }
  153.  
  154. /* find (a) Workbench window */
  155. static struct Window *
  156.    FindWBWindow()
  157. {
  158.    struct Screen *s = LockPubScreen("Workbench");
  159.    if (s)
  160.    {
  161.       struct Window *w = s->FirstWindow;
  162.       WBenchToFront();
  163.       Forbid();
  164.       for (; w; w = w->NextWindow)
  165.          if (w->Flags & WFLG_WBENCHWINDOW)
  166.             break;
  167.       Permit();
  168.       UnlockPubScreen(NULL, s);
  169.       return w;
  170.    }
  171.    return NULL;
  172. }
  173.  
  174. /* bring a palette up on screen */
  175. /* CreateNewProc this function... */
  176. static SAVEDS void
  177.    DoPalette()
  178. {
  179.    struct ReqToolsBase *ReqToolsBase;
  180.    struct Screen       *mousescr;
  181.    struct Window       *win;
  182.    STRPTR               title=getString(Palette_Title);
  183.    LONG                 tags[3];
  184.    
  185.    if (ReqToolsBase = (void *)OpenLibrary("reqtools.library", 0L))
  186.    {
  187.       mousescr = ReqToolsBase->IntuitionBase->FirstScreen;
  188.       
  189.       win=mousescr->FirstWindow;
  190.       
  191.       while (win)
  192.       {
  193.          if ((win->Title) && !strcmp(title, win->Title))
  194.          {
  195.             WindowToFront(win);
  196.             ActivateWindow(win);
  197.             return;
  198.          }
  199.          win=win->NextWindow;
  200.       }
  201.       
  202.       palette_count++;
  203.       
  204.       tags[0] = RT_Screen;
  205.       tags[1] = (LONG)mousescr;
  206.       tags[2] = TAG_DONE;
  207.       (void) rtPaletteRequestA(title, NULL, (struct TagItem *)tags);
  208.       CloseLibrary((struct Library *)ReqToolsBase);
  209.    }
  210.    palette_count--;
  211. }
  212.  
  213. /*
  214.  * Asynchronous external command started with its own autocon Input/Output
  215.  * Result will only reflect whether System() call itself succeeded.
  216.  * If System() call fails, result will be -1L; -2L for window failure.
  217.  * We are using -2L as result if our Open of CON: fails
  218.  */
  219. #define AUTOCON "CON:0/25/640/150/Yak Command/AUTO/CLOSE/WAIT/ALT0/25/80/50"
  220. static LONG
  221.    beginCommand(char *command, LONG Stack, LONG Priority)
  222. {
  223.    static ULONG stags[] = {
  224.       SYS_Input, NULL,
  225.       SYS_Output, NULL,
  226.       SYS_Asynch, TRUE,
  227.       SYS_UserShell, TRUE,
  228.       NP_Priority, 0L,
  229.       NP_StackSize, 4000L,
  230. #ifndef USE_WB2CLI
  231.       NP_Path, 0L,
  232. #endif
  233.       TAG_DONE
  234.       };
  235.    BPTR file;
  236.    char *filename;
  237.    
  238. #ifdef NOTDEF                   /* will this screw up sometimes? */
  239.    char *t;
  240.    int inquote = FALSE, usecon = TRUE;
  241.    
  242.    /* determine (simple-mindedly) whether there's redirection */
  243.    for (t = command; *t; t++)
  244.    {
  245.       if (*t == '\"')
  246.          if (t <= command || t[-1] != '*')
  247.             inquote ^= 1;
  248.       if (!inquote)
  249.          if (*t == '>')
  250.          {
  251.             usecon = FALSE;
  252.             break;
  253.          }
  254.    }
  255.    
  256.    filename = usecon ? AUTOCON : "NIL:";
  257. #else
  258.    filename = AUTOCON;
  259. #endif
  260.    if (file = Open(filename, MODE_OLDFILE))
  261.    {
  262.       stags[1] = (ULONG)file;
  263.       stags[9] = Priority;
  264.       
  265.       if (Stack>0)
  266.       {
  267.          stags[11] = Stack;
  268.       }
  269.       
  270. #ifndef USE_WB2CLI
  271.       if (WBMsg)
  272.       {
  273.          stags[13] = (ULONG) CloneWorkbenchPath(WBMsg); 
  274.       }
  275. #endif
  276.       return(SystemTagList(command, (struct TagItem *)stags));
  277.    }
  278.    else return(-2);
  279. }
  280.  
  281.  
  282. /* execute a command */
  283. void
  284.    act_ExecuteCommand(YakHotKey *yhk)
  285. {
  286.    LONG rc;
  287.    
  288.    if (yhk->yhk_Option[1].ArgStr[0])
  289.    {
  290.       ChangeScreen(&yhk->yhk_Option[0]);
  291.       
  292.       if (yhk->yhk_Option[1].Flags & HKO_CLI_COMMAND)
  293.       {
  294.          rc = beginCommand(yhk->yhk_Option[1].ArgStr[0], 
  295.                            yhk->yhk_Option[1].ArgNum[0], 
  296.                            yhk->yhk_Option[1].ArgNum[1]);
  297.       }
  298.       else
  299.       {
  300.          rc = SendARexxCommand(yhk->yhk_Option[1].ArgStr[1], yhk->yhk_Option[1].ArgStr[0]);
  301.       }
  302.       if (rc != 0)
  303.          PostError("%s\n\"%s\"",
  304.                    getString(Couldnt_execute_command_ERR), 
  305.                    yhk->yhk_Option[1].ArgStr[0]);
  306.    }
  307.    else 
  308.       PostError("%s\"%s\".", 
  309.                 getString(No_cmd_specified_for_hotkey_ERR), 
  310.                 yhk->yhk_KeyDef);
  311. }
  312.  
  313.  
  314. /* CloseEvent is declared as static to save some bytes and speed up code */
  315. static struct InputEvent CloseEvent = { NULL, IECLASS_CLOSEWINDOW, 0, 0, 0, 0 };
  316.  
  317. void
  318.    act_CloseWindow(YakHotKey *yhk)
  319. {
  320.    struct Window *window;
  321.    struct Window *CurrentWindow = NULL;
  322.    
  323.    CurrentWindow = ActiveWindow();
  324.    
  325.    if (window = SelectWindow(&yhk->yhk_Option[0]))
  326.    {
  327.       if (window && (window->Flags & CLOSEGADGET))
  328.       {
  329.          ActivateWindow(window);
  330.          AddIEvents(&CloseEvent);
  331.          
  332.          do 
  333.          {
  334.             Delay(1);
  335.          } while (window == ActiveWindow());
  336.          
  337.          if (CurrentWindow && (window != CurrentWindow))
  338.          {
  339.             ActivateWindow(CurrentWindow);
  340.          }
  341.          else
  342.          {   
  343.             if (autopoint)
  344.             {
  345.                ActivateMouseWindow (KEY);
  346.             }
  347.          }
  348.       }
  349.    }
  350. }
  351.  
  352.  
  353.  
  354. /*
  355.  * This function simulates Intuition mutual exclusion for menu items.
  356.  */ 
  357.  
  358. static __regargs void
  359.    UnCheckExcludedItems(UWORD  menu, 
  360.                         UWORD  item, 
  361.                         UWORD  sub, 
  362.                         ULONG MutualExclude, 
  363.                         struct Window *window)
  364. {
  365.    struct MenuItem *menuitem;
  366.    UWORD  menuNumber;
  367.    UBYTE  i=0;
  368.    
  369.    while (MutualExclude > 0)
  370.    {
  371.       if (MutualExclude & 1)
  372.       {
  373.          /* Item to exclude */
  374.          
  375.          if (sub == NOSUB)
  376.          {
  377.             item = i;
  378.          }
  379.          else
  380.          {
  381.             sub = i;
  382.          }
  383.          
  384.          menuNumber = FULLMENUNUM( menu, item, sub );
  385.          menuitem = ItemAddress(window->MenuStrip, menuNumber);
  386.          
  387.          if ((menuitem) &&                     /* item must exist      */
  388.              (menuitem->Flags & ITEMENABLED) && /* item must be enabled */
  389.              (menuitem->Flags & CHECKED))       /* item must be checked */
  390.          {
  391.             menuitem->Flags &= ~CHECKED;
  392.          }
  393.       }
  394.       MutualExclude = MutualExclude >> 1;
  395.       i++;
  396.    }
  397. }
  398.  
  399.  
  400. /* MenuEvent is declared as static to save some bytes and speed up code */
  401. static struct InputEvent MenuEvent = { NULL, IECLASS_MENULIST, 0, 0, IEQUALIFIER_LEFTBUTTON, 0 };
  402.  
  403. void
  404.    act_MenuShortcut(YakHotKey *yhk)
  405. {
  406.    struct Window *window;
  407.    struct MenuItem *menuitem;
  408.    UWORD  menuNumber, menu, item, sub;
  409.    
  410.    window = ActiveWindow();
  411.    
  412.    menu = (UWORD) yhk->yhk_Option[0].ArgNum[0];
  413.    item = (UWORD) yhk->yhk_Option[0].ArgNum[1];
  414.    
  415.    if (yhk->yhk_Option[0].Flags & HKO_SUBITEM)
  416.    {
  417.       sub = (UWORD) yhk->yhk_Option[0].ArgNum[2];
  418.    }
  419.    else
  420.    {
  421.       /* no subitem specified */
  422.       sub = NOSUB;
  423.    }
  424.    
  425.    if (window && (window->MenuStrip))
  426.    {
  427.       menuNumber = FULLMENUNUM( menu, item, sub );
  428.       menuitem = ItemAddress(window->MenuStrip, menuNumber);
  429.       
  430.       if ((menuitem) &&                  /* item must exist             */
  431.           (menuitem->Flags & ITEMENABLED)) /* item must be enabled        */
  432.       {
  433.          /* We don't want multi selection */
  434.          menuitem->NextSelect = MENUNULL;
  435.          
  436.          /* Take care of checkit items */
  437.          if (menuitem->Flags & CHECKIT)
  438.          {
  439.             if (menuitem->Flags & MENUTOGGLE) 
  440.             {
  441.                if (menuitem->Flags & CHECKED)
  442.                {
  443.                   /* If it's already checked, uncheck it */
  444.                   menuitem->Flags &= ~CHECKED;
  445.                }
  446.                else
  447.                {
  448.                   /* If it's unchecked, check it */
  449.                   menuitem->Flags |= CHECKED;
  450.                }
  451.             }
  452.             else 
  453.             {
  454.                /* Mutual Exclude */
  455.                if ((menuitem->Flags & CHECKED) == FALSE)
  456.                {
  457.                   /* check it */
  458.                   menuitem->Flags |= CHECKED;
  459.                   
  460.                   /* and then take care of excluded items */
  461.                   UnCheckExcludedItems(menu, item, sub, menuitem->MutualExclude, window);
  462.                }
  463.             }
  464.          }
  465.          
  466.          /* Send our event */
  467.          MenuEvent.ie_Code         = menuNumber;
  468.          MenuEvent.ie_EventAddress = window;
  469.          
  470.          AddIEvents(&MenuEvent);
  471.       }
  472.    }
  473.    
  474. }
  475.  
  476. /* HideWindow().
  477.  * This is the key to window iconification. This call removes the window
  478.  * from the display without releasing any of it's attributes. This is   
  479.  * sort of a visual trick: the layer of the window is made small (one   
  480.  * pixel), and is moved to the lower rightmost position of the display. 
  481.  * Thus the window is invisible, but it keeps it's rastport, bitmap,    
  482.  * gadgets, etc... The only way the trick can be seen is by checking    
  483.  * Intuition's window list, or by using a program such as DropShadow 
  484.  * which highlights window levels.
  485.  * This screws up with programs messing with layers, of course, but
  486.  * they are pretty rare.                           
  487.  */
  488.  
  489. static VOID
  490.    HideWindow(struct Window *window)
  491. {
  492.    struct   Screen      *screen;
  493.    struct   Screen      *wb;
  494.    
  495.    screen = window->WScreen;
  496.    
  497.    MoveSizeLayer(window->RPort->Layer,
  498.                  screen->Width  - window->LeftEdge - 1,
  499.                  screen->Height - window->TopEdge  - 1,
  500.                  1-window->Width,
  501.                  1-window->Height);
  502.  
  503.  
  504.    if ((wb = LockPubScreen("Workbench")) &&
  505.        (wb == screen) &&
  506.        (fullworkbench == TRUE))
  507.    {
  508.       ShowTitle(screen, FALSE);
  509.    }
  510.    else
  511.    {
  512.       ShowTitle(screen, TRUE);
  513.    }
  514.    UnlockPubScreen(NULL, wb);
  515.  
  516.    MakeScreen(screen);
  517. }
  518.  
  519. /* RevealWindow() is the exact opposition of HideWindow(). It resizes and
  520.  * puts back to its original position the window's layer. The nice thing 
  521.  * about it is that we DO NOT need to give it the position where to move 
  522.  * to: this is described by the window itself!
  523.  */
  524.  
  525. /* RefreshEvent is declared as static to save some bytes and speed up code */
  526. static struct InputEvent RefreshEvent = { NULL, IECLASS_REFRESHWINDOW, 0, 0, 0, 0 };
  527.  
  528. VOID
  529.    RevealWindow(struct Window *window)
  530. {
  531.    struct Screen *screen;
  532.    ULONG          lock;
  533.    BOOL           WindowFound = FALSE;
  534.    struct Window *win = NULL;
  535.    
  536.    /* First check that our window still exists */
  537.    
  538.    lock = LockIBase(0);
  539.    
  540.    screen = IntuitionBase->FirstScreen;
  541.    
  542.    while ((screen != NULL) && (WindowFound == FALSE))
  543.    {
  544.       win = screen->FirstWindow;
  545.       
  546.       while ((win != NULL) && (WindowFound == FALSE))
  547.       {
  548.          WindowFound = (win == window);
  549.          win = win->NextWindow;
  550.       }
  551.       screen = screen->NextScreen;
  552.    }
  553.    UnlockIBase(lock);
  554.    
  555.    if (WindowFound == TRUE)
  556.    {
  557.       screen = window->WScreen;
  558.  
  559.       MoveSizeLayer(window->RPort->Layer,
  560.                     window->LeftEdge - screen->Width  + 1,
  561.                     window->TopEdge  - screen->Height + 1,
  562.                     window->Width-1,
  563.                     window->Height-1);
  564.  
  565.         ScreenToFront(screen);
  566.         WindowToFront(window);
  567.    }
  568. }
  569.  
  570. void
  571.    act_IconifyWindow(YakHotKey *yhk)
  572. {
  573.    struct Window *window;
  574.    ULONG lock;
  575.    
  576.    lock = LockIBase(0);
  577.    window = SelectWindow(&yhk->yhk_Option[0]);
  578.     UnlockIBase(lock);
  579.  
  580.    if ((window != NULL) &&
  581.          !(window->Flags & WFLG_BACKDROP) &&
  582.          (MakeAppIconified(window) == TRUE))
  583.    {
  584.       HideWindow(window);
  585.  
  586.         /* Activate another window */
  587.         ActivateMouseWindow(SCREEN);
  588.    }
  589. }
  590.  
  591. void
  592.    act_ZipWindow(YakHotKey *yhk)
  593. {
  594.    struct Window *window;
  595.    ULONG lock;
  596.    
  597.    lock = LockIBase(0);
  598.    if (window = SelectWindow(&yhk->yhk_Option[0]))
  599.    {
  600.       if (window->Flags & WFLG_HASZOOM)
  601.          ZipWindow(window);
  602.    }
  603.    UnlockIBase(lock);
  604. }
  605.  
  606. void
  607.    act_ShrinkWindow(YakHotKey *yhk)
  608. {
  609.    struct Window *window;
  610.    ULONG lock;
  611.    
  612.    lock = LockIBase(0);
  613.    if (window = SelectWindow(&yhk->yhk_Option[0]))
  614.    {
  615.       if (window->Flags & WFLG_SIZEGADGET)
  616.          ChangeWindowBox(window,
  617.                          window->LeftEdge,
  618.                          window->TopEdge,
  619.                          window->MinWidth,
  620.                          window->MinHeight);
  621.    }
  622.    UnlockIBase(lock);
  623. }
  624.  
  625. void
  626.    act_ExpandWindow(YakHotKey *yhk)
  627. {
  628.    struct Window  *win;
  629.    ULONG           lock;
  630.    
  631.    lock = LockIBase(0);
  632.    
  633.    if (win = SelectWindow(&yhk->yhk_Option[0]))
  634.    {
  635.       if (win->Flags & WFLG_SIZEGADGET)
  636.       {
  637.          EnlargeWindow(win, yhk->yhk_Option[1].Flags);
  638.       }
  639.    }
  640.    
  641.    UnlockIBase(lock);
  642. }
  643.  
  644.  
  645. void
  646.    act_MoveWindow(YakHotKey *yhk)
  647. {
  648.    struct Window  *win;
  649.    WORD            top, left,
  650.    width, height;
  651.    ULONG           lock;
  652.    struct IBox     box;
  653.    struct Screen  *s;
  654.    
  655.    lock = LockIBase(0);
  656.    
  657.    if (win=SelectWindow(&yhk->yhk_Option[0]))
  658.    {
  659.       
  660.       if (win->Flags & WFLG_DRAGBAR)
  661.       {
  662.          top    = win->TopEdge;
  663.          left   = win->LeftEdge;
  664.          width  = win->Width;
  665.          height = win->Height;
  666.          s      = win->WScreen;
  667.          
  668.          
  669.          GetScreenBox(s, &box, (yhk->yhk_Option[1].Flags & HKO_MOVE_VISIBLE_BAR));
  670.          
  671.          if (yhk->yhk_Option[1].Flags & HKO_MOVE_LEFT)
  672.             left = box.Left;
  673.          
  674.          if (yhk->yhk_Option[1].Flags & HKO_MOVE_HORIZONTAL_CENTER)
  675.             left = box.Left + (box.Width-width)>>1;
  676.          
  677.          if (yhk->yhk_Option[1].Flags & HKO_MOVE_RIGHT)
  678.             left = box.Left + box.Width - width;
  679.          
  680.          if (yhk->yhk_Option[1].Flags & HKO_MOVE_TOP)
  681.             top = box.Top;
  682.          
  683.          if (yhk->yhk_Option[1].Flags & HKO_MOVE_VERTICAL_CENTER)
  684.             top = box.Top + (box.Height-height)/2;
  685.          
  686.          if (yhk->yhk_Option[1].Flags & HKO_MOVE_BOTTOM)
  687.             top = box.Top + box.Height - height;
  688.          
  689.          if (win->LeftEdge != left || win->TopEdge != top)
  690.             ChangeWindowBox(win,
  691.                             left,
  692.                             top,
  693.                             width,
  694.                             height);
  695.          
  696.       }
  697.    }
  698.    
  699.    UnlockIBase(lock);
  700. }
  701.  
  702.  
  703. /*
  704.  * This function tells if a window has to be cycled according to 
  705.  * the cycling options
  706.  */
  707.  
  708. __regargs BOOL
  709.    MatchWindow(struct Window *win, UWORD Options, STRPTR Pattern)
  710. {
  711.    BOOL result;
  712.    struct Task *WinTask;
  713.    STRPTR TaskName;
  714.    
  715.    if (win)
  716.    {
  717.       if (Options & HKO_EXCLUDE_WB_DRAWERS) 
  718.       {
  719.          result = !(win->Flags & WFLG_WBENCHWINDOW);
  720.       }
  721.       else
  722.       {
  723.          result = TRUE;
  724.       }
  725.       
  726.       if ((result==TRUE) && !(Options & HKO_ACTIVATE_ONLY)) 
  727.       {
  728.          result = !(win->Flags & WFLG_BACKDROP);
  729.       }
  730.       
  731.       if ((result==TRUE) && (Options & HKO_BY_WINDOW_TASK_NAME))
  732.       {
  733.          /* This is the task attached to our window */
  734.          if ((WinTask = win->UserPort->mp_SigTask) &&
  735.              (TaskName = WinTask->tc_Node.ln_Name))
  736.          {
  737.             /* Does its name match our pattern? */
  738.             result = MatchPattern(Pattern, TaskName);
  739.          }
  740.          else
  741.          {
  742.             result = FALSE;
  743.          }
  744.       }
  745.    }
  746.    else
  747.    {
  748.       result = FALSE;
  749.    }
  750.    
  751.    return(result);
  752. }
  753.  
  754.  
  755. /* This function cycle through specified windows 
  756.  * WARNING: it must be called under Forbid()/LockIBase()
  757.  */
  758. void
  759.    SelectiveCycleWindows(struct Screen *s, 
  760.                          UWORD Options, 
  761.                          STRPTR Pattern)
  762. {
  763.    struct Layer  *l;
  764.    struct Window *curwin = NULL;
  765.    struct Window *next;
  766.    struct Window *backmost = NULL;
  767.    
  768.    if (l = s->LayerInfo.top_layer)
  769.    {
  770.       /* starting from top layer one, find backmost window 
  771.        * that matches our criterias
  772.        */
  773.       for (l = s->LayerInfo.top_layer; l; l = l->back)
  774.       {
  775.          curwin = (struct Window *)l->Window;
  776.          if (MatchWindow(curwin, Options, Pattern))
  777.             backmost = curwin;
  778.       }   
  779.       
  780.       l = backmost->WLayer;
  781.       
  782.       if (Options & HKO_ACTIVATE_ONLY)
  783.       {
  784.          if ((IntuitionBase->ActiveWindow) &&
  785.              (IntuitionBase->ActiveWindow->WScreen == s))
  786.          {
  787.             curwin = IntuitionBase->ActiveWindow;
  788.          }                  
  789.          else
  790.          {
  791.             curwin = s->FirstWindow;
  792.          }
  793.       }
  794.       else
  795.       {
  796.          curwin = backmost;
  797.       }
  798.       
  799.       if (curwin)
  800.       {
  801.          l = curwin->WLayer; 
  802.          next = curwin;
  803.          
  804.          if (Options & HKO_ACTIVATE_ONLY)
  805.          {
  806.             while (l && 
  807.                    (!MatchWindow(next, Options, Pattern) ||
  808.                     (next == curwin)))
  809.             {
  810.                next = (struct Window *)l->Window;
  811.                l = l->front;
  812.             } 
  813.             if (next == curwin)
  814.             {
  815.                /* We have reached TopLayer window, so go back to back most one */
  816.                next = backmost;
  817.             }
  818.          }
  819.          else
  820.          {
  821.             while (l && 
  822.                    !MatchWindow(next, Options, Pattern))
  823.             {
  824.                next = (struct Window *)l->Window;
  825.                l = l->front;
  826.             } 
  827.             ScreenToFront(next->WScreen);
  828.             WindowToFront(next);
  829.          }
  830.          ActivateWindow(next);
  831.       }
  832.    }
  833. }
  834.  
  835.  
  836. /* 
  837.  * This function cycle through specified windows but in the inverse 
  838.  * direction as the one used by SelectiveCycleWindows().
  839.  * WARNING: it must be called under Forbid()/LockIBase()
  840.  * 
  841.  */
  842.  
  843. void
  844.    SelectiveBackCycleWindows(struct Screen *s, 
  845.                              UWORD Options, 
  846.                              STRPTR Pattern)
  847. {
  848.    struct Layer  *l;
  849.    struct Window *frontmost;
  850.    struct Window *previous;
  851.    struct Window *curwin = NULL;
  852.    
  853.    if (l = s->LayerInfo.top_layer)
  854.    {
  855.       /* starting from top layer one, find frontmost window that matches
  856.        * our criterias.
  857.        */
  858.       frontmost = NULL;
  859.       
  860.       while (l && !MatchWindow(frontmost, Options, Pattern))
  861.       {
  862.          frontmost = (struct Window *)l->Window;        
  863.          l = l->back;   
  864.       }
  865.       
  866.       if (frontmost)
  867.       {
  868.          if (Options & HKO_ACTIVATE_ONLY)
  869.          {
  870.             if ((IntuitionBase->ActiveWindow) &&
  871.                 (IntuitionBase->ActiveWindow->WScreen == s))
  872.             {
  873.                curwin = IntuitionBase->ActiveWindow;
  874.             }   
  875.             else
  876.             {
  877.                curwin = s->FirstWindow;
  878.             }
  879.          }
  880.          else
  881.          {
  882.             curwin = frontmost;
  883.             if (MatchWindow(curwin, Options, Pattern))
  884.             {
  885.                WindowToBack(curwin);
  886.             }
  887.          }
  888.          
  889.          /* find the frontmost matching window by starting from the top layer 
  890.           * We must take care to exclude the window we start from.
  891.           */
  892.          
  893.          
  894.          l = curwin->WLayer;
  895.          previous = curwin;
  896.          
  897.          while (l && 
  898.                 (!MatchWindow(previous, Options, Pattern) ||
  899.                  (previous == curwin))) 
  900.          {
  901.             previous = (struct Window *)l->Window;
  902.             l = l->back;
  903.          } 
  904.          
  905.          if ((l == NULL) && ((previous == NULL) || (previous == curwin)))
  906.          {
  907.             /* We have reached the backmost window.*/
  908.             previous = frontmost;   
  909.          }
  910.          
  911.          if (!(Options & HKO_ACTIVATE_ONLY))
  912.          {
  913.             WindowToFront(previous);
  914.          }
  915.          ActivateWindow(previous);
  916.       }
  917.    }
  918. }
  919.  
  920.  
  921. void
  922.    act_CycleWindows(YakHotKey *yhk)
  923. {
  924.    struct Screen *s;
  925.    PatternData   pdata = {"",NULL};
  926.    ULONG lock;
  927.    
  928.    if (s = SelectScreen(&yhk->yhk_Option[0]))
  929.    {
  930.       if (yhk->yhk_Option[1].Flags & HKO_BY_WINDOW_TASK_NAME)
  931.       {
  932.          InitPattern(yhk->yhk_Option[1].ArgStr[0], &pdata);
  933.       }
  934.       
  935.       lock = LockIBase(0);
  936.       Forbid();
  937.       
  938.       if (yhk->yhk_Option[1].Flags & HKO_BACK_CYCLE) 
  939.       {
  940.          SelectiveBackCycleWindows(s, yhk->yhk_Option[1].Flags, pdata.pat);
  941.       } 
  942.       else
  943.       {
  944.          SelectiveCycleWindows(s, yhk->yhk_Option[1].Flags, pdata.pat);
  945.       }
  946.       
  947.       Permit();
  948.       UnlockIBase(lock);
  949.       
  950.       FreeVec(pdata.pat);
  951.    }
  952.    
  953. }   
  954.  
  955.  
  956. /* taglist for CreateNewProc */
  957. static LONG palette_taglist[] = {
  958.    NP_Entry, (LONG)DoPalette,
  959.    NP_Name, (LONG)"Yak Palette",
  960.    TAG_DONE
  961.    };
  962.  
  963. void
  964.    act_OpenPalette(YakHotKey *yhk)
  965. {
  966.    ChangeScreen(&yhk->yhk_Option[0]);
  967.    
  968.    CreateNewProc((struct TagItem *)palette_taglist);
  969. }
  970.  
  971. void
  972.    act_ScreenToFront(YakHotKey *yhk)
  973. {
  974.    struct Screen *s;
  975.    
  976.    if (s=SelectScreen(&yhk->yhk_Option[0]))
  977.    {
  978.       MyScreenToFront(s);
  979.    }
  980. }
  981.  
  982. void
  983.    act_ScreenToBack(YakHotKey *yhk)
  984. {
  985.    struct Screen *s;
  986.    
  987.    if (s=SelectScreen(&yhk->yhk_Option[0]))
  988.    {
  989.       MyScreenToBack(s);
  990.    }
  991. }
  992.  
  993. void
  994.    act_ActivateWorkbench(YakHotKey *yhk)
  995. {
  996.    struct Window *w;
  997.    
  998.    if (w = FindWBWindow())
  999.    {
  1000.       WBenchToFront();
  1001.       ActivateWindow(w);
  1002.    }
  1003. }
  1004.  
  1005. void
  1006.    act_MoveScreen(YakHotKey *yhk)
  1007. {
  1008.    struct Screen *scr;
  1009.    
  1010.    if (scr = SelectScreen(&yhk->yhk_Option[0]))
  1011.    {
  1012.       YakMoveScreen(scr, yhk->yhk_Option[1].Flags);
  1013.    }
  1014. }
  1015.  
  1016. void
  1017.    act_BlankDisplay(YakHotKey *yhk)
  1018. {
  1019.    BlankScreen();
  1020. }
  1021.  
  1022. void
  1023.    act_InsertText(YakHotKey *yhk)
  1024. {
  1025.    if (yhk->yhk_Option[0].ArgStr[0])
  1026.    {
  1027.       if (!AddToStream(yhk->yhk_Option[0].ArgStr[0], (UBYTE)yhk->yhk_Option[0].ArgNum[0]))
  1028.          PostError("%s:\n \"%s\"", 
  1029.                    getString(Text_insertion_str_invalid_ERR), yhk->yhk_Option[0].ArgStr[0]);
  1030.    }
  1031.    else PostError("%s \"%s\" %s", 
  1032.                   getString(Yak_text_hotkey_ERR),
  1033.                   yhk->yhk_KeyDef,
  1034.                   getString(Has_no_text_specified_ERR));
  1035. }
  1036.  
  1037. void
  1038.    act_InsertDate(YakHotKey *yhk)
  1039. {
  1040.    struct DateTime dat;
  1041.    DateStamp(&dat.dat_Stamp);
  1042.    
  1043.    if (LocaleBase)
  1044.    {
  1045.       if (yhk->yhk_Option[0].ArgStr[0])
  1046.          FormatDate(locale, yhk->yhk_Option[0].ArgStr[0], &dat.dat_Stamp, &putcharhook);
  1047.       else PostError("%s \"%s\" %s", 
  1048.                      getString(Yak_date_hotkey_ERR),
  1049.                      yhk->yhk_KeyDef,
  1050.                      getString(Has_no_format_specified_ERR));
  1051.    }
  1052.    else
  1053.    {
  1054.       /* pre-2.1 OS */
  1055.       char datestr[LEN_DATSTRING];
  1056.       
  1057.       dat.dat_Format = FORMAT_DOS;
  1058.       dat.dat_Flags = 0;
  1059.       dat.dat_StrDate = datestr;
  1060.       dat.dat_StrDay = dat.dat_StrTime = NULL;
  1061.       DateToStr(&dat);
  1062.       AddToStream(datestr, 0);
  1063.    }
  1064. }
  1065.  
  1066.  
  1067. void
  1068.    act_ShowInterface(YakHotKey *yhk)
  1069. {
  1070.    ChangeScreen(&yhk->yhk_Option[0]);
  1071.    ShowYakInterface();
  1072. }
  1073.  
  1074.  
  1075.  
  1076. /* Set the active screen as default public screen if it a public screen 
  1077.  ** else do nothing.
  1078.  **/
  1079. void
  1080.    act_CurrentScreenAsDefPub(YakHotKey *yhk)
  1081. {
  1082.    UBYTE *PSName;
  1083.    struct Screen *s;
  1084.    
  1085.    /* Get the active screen */
  1086.    s = ActiveScreen();
  1087.    
  1088.    /* Get the name of our screen if it is a public screen */
  1089.    PSName = GetPubScreenName(s);
  1090.    
  1091.    if (PSName)
  1092.    {
  1093.       /* active screen is a public screen so 
  1094.        * make it default public screen
  1095.        */
  1096.       SetDefaultPubScreen(PSName);
  1097.    }
  1098. }
  1099.  
  1100.  
  1101.  
  1102. static void __regargs
  1103.    YakMoveScreen(struct Screen *scr, UWORD flags)
  1104. {
  1105.    struct Window    *win;
  1106.    struct Rectangle  rect;
  1107.    struct IBox       b_box, f_box;
  1108.    ULONG             modeid;
  1109.    WORD              dx=0,dy=0;
  1110.    
  1111.    if ( (modeid = GetVPModeID(&scr->ViewPort)) != INVALID_ID &&
  1112.        QueryOverscan(modeid, &rect, OSCAN_TEXT))
  1113.    {
  1114.       if((flags & HKO_MOVE_VISIBLE_BAR) &&
  1115.          (win=ActiveWindow()) &&
  1116.          (win->WScreen == scr))
  1117.       {
  1118.          GetScreenBox(scr, &b_box, FALSE);
  1119.          f_box.Left   = win->LeftEdge;
  1120.          f_box.Top    = win->TopEdge;
  1121.          f_box.Width  = win->Width;
  1122.          f_box.Height = win->Height;
  1123.       }
  1124.       else
  1125.       {
  1126.          b_box.Left   = rect.MinX;
  1127.          b_box.Top    = rect.MinY;
  1128.          b_box.Width  = rect.MaxX - rect.MinX + 1;
  1129.          b_box.Height = rect.MaxY - rect.MinY + 1;
  1130.          f_box.Left   = scr->LeftEdge;
  1131.          f_box.Top    = scr->TopEdge;
  1132.          f_box.Width  = scr->Width;
  1133.          f_box.Height = scr->Height;
  1134.       }
  1135.       
  1136.       if (flags & HKO_MOVE_LEFT)
  1137.          dx = b_box.Left - f_box.Left;
  1138.       
  1139.       if (flags & HKO_MOVE_HORIZONTAL_CENTER)
  1140.          dx = b_box.Left - f_box.Left + ((b_box.Width - f_box.Width) >> 1);
  1141.       
  1142.       if (flags & HKO_MOVE_RIGHT)
  1143.          dx = b_box.Left - f_box.Left + b_box.Width - f_box.Width;
  1144.       
  1145.       if (flags & HKO_MOVE_TOP)
  1146.          dy = b_box.Top - f_box.Top;
  1147.       
  1148.       if (flags & HKO_MOVE_VERTICAL_CENTER)
  1149.          dx = b_box.Top - f_box.Top + ((b_box.Height - f_box.Height) >> 1);
  1150.       
  1151.       if (flags & HKO_MOVE_BOTTOM)
  1152.          dy = b_box.Top - f_box.Top + b_box.Height - f_box.Height;
  1153.       
  1154.       MoveScreen(scr, dx, dy);
  1155.    }
  1156. }
  1157.  
  1158.  
  1159. static void __regargs
  1160.    EnlargeWindow(struct Window *win, UWORD flags)
  1161. {
  1162.    WORD            width  = win->Width,
  1163.    height = win->Height,
  1164.    top    = win->TopEdge,
  1165.    left   = win->LeftEdge,
  1166.    l;
  1167.    struct IBox     box;
  1168.    struct Screen  *s = win->WScreen;
  1169.    
  1170.    GetScreenBox(s, &box, flags & HKO_RESIZE_VISIBLE_BAR);
  1171.    
  1172.    if (flags & HKO_RESIZE_HORIZONTAL)
  1173.    {
  1174.       width = win->MaxWidth;
  1175.       if (width == -1 || width > box.Width)
  1176.          width = box.Width;
  1177.       if (left < box.Left)
  1178.       {
  1179.          left = box.Left;
  1180.       } 
  1181.       else
  1182.       {
  1183.          if ((l = box.Left + box.Width - left - width) < 0)
  1184.             left += l;
  1185.       }
  1186.    }
  1187.    if (flags & HKO_RESIZE_VERTICAL)
  1188.    {
  1189.       height = win->MaxHeight;
  1190.       if (height == -1 || height > box.Height)
  1191.          height = box.Height;
  1192.       
  1193.       if (top < box.Top)
  1194.       {
  1195.          top = box.Top;
  1196.       } else
  1197.       {
  1198.          if ((l = box.Top + box.Height - top - height) < 0)
  1199.             top += l;
  1200.       }
  1201.    }
  1202.    if (win->LeftEdge != left || win->TopEdge != top ||
  1203.        win->Width != width || win->Height != height)
  1204.       ChangeWindowBox(win,
  1205.                       left,
  1206.                       top,
  1207.                       width,
  1208.                       height);
  1209. }
  1210.  
  1211.  
  1212.  
  1213. static struct Window *
  1214.    ActiveWindow(void)
  1215. {
  1216.    ULONG lock;
  1217.    struct Window *window=NULL;
  1218.    
  1219.    lock = LockIBase(0);
  1220.    window = IntuitionBase->ActiveWindow;
  1221.    UnlockIBase(lock);
  1222.    
  1223.    return window;
  1224. }
  1225.  
  1226.  
  1227.  
  1228.  
  1229. static struct Window *
  1230.    WindowByTitle(STRPTR title)
  1231. {
  1232.    struct Screen *screen      = NULL;
  1233.    struct Window *window      = NULL;
  1234.    BOOL           WindowFound = FALSE;
  1235.    PatternData    pdata       = {"",NULL};
  1236.    
  1237.    if (InitPattern(title, &pdata))
  1238.    {
  1239.       ULONG lock = LockIBase(0);
  1240.       
  1241.       screen = IntuitionBase->FirstScreen;
  1242.       
  1243.       while (screen && (WindowFound == FALSE))
  1244.       {
  1245.          window = screen->FirstWindow;
  1246.          
  1247.          while (window && (WindowFound == FALSE))
  1248.          {
  1249.             if (window->Title)
  1250.             {
  1251.                WindowFound = MatchPattern(pdata.pat, window->Title);
  1252.             }
  1253.             if (WindowFound == FALSE)
  1254.             {
  1255.                window = window->NextWindow;
  1256.             }
  1257.          }
  1258.          screen = screen->NextScreen;
  1259.       }
  1260.       
  1261.       UnlockIBase(lock);
  1262.       
  1263.       FreeVec(pdata.pat);
  1264.    }
  1265.    
  1266.    if (WindowFound == TRUE)
  1267.    {
  1268.       return(window);
  1269.    }
  1270.    else
  1271.    {
  1272.       return(NULL);
  1273.    }
  1274. }
  1275.  
  1276.  
  1277. static struct Screen *
  1278.    ActiveScreen(void)
  1279. {
  1280.    ULONG lock;
  1281.    struct Screen *screen=NULL;
  1282.    
  1283.    lock = LockIBase(0);
  1284.    screen = IntuitionBase->ActiveScreen;
  1285.    UnlockIBase(lock);
  1286.    
  1287.    return (screen);
  1288. }
  1289.  
  1290.  
  1291.  
  1292. static struct Screen *
  1293.    ScreenByTitle(STRPTR title)
  1294. {
  1295.    struct Screen *screen      = NULL;
  1296.    PatternData    pdata       = {"",NULL};
  1297.    BOOL           ScreenFound = FALSE;
  1298.    
  1299.    if (InitPattern(title, &pdata))
  1300.    {
  1301.       ULONG lock = LockIBase(0);
  1302.       
  1303.       screen = IntuitionBase->FirstScreen;
  1304.       
  1305.       while (screen && !ScreenFound)
  1306.       {
  1307.          if (screen->DefaultTitle)
  1308.          {
  1309.             ScreenFound=MatchPattern(pdata.pat, screen->DefaultTitle);
  1310.          }
  1311.          if (ScreenFound == FALSE) 
  1312.          {
  1313.             screen = screen->NextScreen;
  1314.          }
  1315.       }
  1316.       
  1317.       UnlockIBase(lock);
  1318.       
  1319.       FreeVec(pdata.pat);
  1320.    }
  1321.    
  1322.    if (ScreenFound)
  1323.    {
  1324.       return(screen);
  1325.    }
  1326.    else
  1327.    {
  1328.       return(NULL);
  1329.       
  1330.    }
  1331. }
  1332.  
  1333. struct Screen *
  1334.    RearmostScreen(void)
  1335. {
  1336.    ULONG lock;
  1337.    struct Screen *screen=NULL, *ns;
  1338.    
  1339.    lock = LockIBase(0);
  1340.    
  1341.    screen = IntuitionBase->FirstScreen;
  1342.    
  1343.    ns = screen->NextScreen;
  1344.    while (ns)
  1345.    {
  1346.       screen = ns;
  1347.       ns     = screen->NextScreen;
  1348.    }
  1349.    
  1350.    UnlockIBase(lock);
  1351.    
  1352.    return screen;
  1353. }
  1354.  
  1355.  
  1356. static struct Screen *
  1357.    FrontmostScreen(void)
  1358. {
  1359.    ULONG lock;
  1360.    struct Screen *screen=NULL;
  1361.    
  1362.    lock = LockIBase(0);
  1363.    screen = IntuitionBase->FirstScreen;
  1364.    UnlockIBase(lock);
  1365.    
  1366.    return screen;
  1367. }
  1368.  
  1369.  
  1370. static struct Window *
  1371.    SelectWindow(YakOption *opt)
  1372. {
  1373.    struct Window *window=NULL;
  1374.    
  1375.    switch (opt->Flags)
  1376.    {
  1377.    case HKO_ACTIVE:
  1378.       window = ActiveWindow();
  1379.       break;
  1380.       
  1381.    case HKO_UNDER_MOUSE:
  1382.       window = WindowUnderMouse();
  1383.       break;
  1384.       
  1385.    case HKO_BY_TITLE|HKO_PATTERN:
  1386.       window = WindowByTitle(opt->ArgStr[0]);
  1387.       break;
  1388.    }
  1389.    return window;
  1390. }
  1391.  
  1392.  
  1393. static struct Screen *
  1394.    SelectScreen(YakOption *opt)
  1395. {
  1396.    struct Screen *screen=NULL;
  1397.    
  1398.    switch (opt->Flags)
  1399.    {
  1400.    case HKO_ACTIVE:
  1401.       screen = ActiveScreen();
  1402.       break;
  1403.       
  1404.    case HKO_UNDER_MOUSE:
  1405.       screen = ScreenUnderMouse();
  1406.       break;
  1407.       
  1408.    case HKO_BY_TITLE|HKO_PATTERN:
  1409.       screen = ScreenByTitle(opt->ArgStr[0]);
  1410.       break;
  1411.       
  1412.    case HKO_REARMOST:
  1413.       screen = RearmostScreen();
  1414.       break;
  1415.       
  1416.    case HKO_FRONTMOST:
  1417.       screen = FrontmostScreen();
  1418.       break;
  1419.    }
  1420.    
  1421.    return screen;
  1422. }
  1423.  
  1424.  
  1425. static void
  1426.    ChangeScreen(YakOption *opt)
  1427. {
  1428.    struct Screen *scr;
  1429.    char *scrname;
  1430.    
  1431.    if (!(opt->Flags & HKO_NO_SCREEN_CHANGE))
  1432.    {
  1433.       switch (opt->Flags)
  1434.       {
  1435.       case HKO_WORKBENCH_TO_FRONT:
  1436.          scrname = "Workbench";
  1437.          break;
  1438.          
  1439.       case HKO_DEFAULT_PUBSCR_TO_FRONT:
  1440.          scrname = NULL;
  1441.          break;
  1442.       }
  1443.       
  1444.       if (scr = LockPubScreen(scrname))
  1445.       {
  1446.          ScreenToFront(scr);
  1447.          UnlockPubScreen(NULL, scr);
  1448.       }
  1449.    }
  1450. }
  1451.  
  1452.  
  1453. /*
  1454.  * the generic hotkey action stub
  1455.  */
  1456. void
  1457.    PerformAction(YakHotKey *yhk)
  1458. {
  1459.    /* and perform action (gobbledegook!? that's C for you...) */
  1460.    (*(yhktypes[yhk->yhk_Type].yhkt_Command))(yhk);
  1461. }
  1462.  
  1463.